/*
 ------------------------------------------------------------------------------
	willy-player - a simple music player based on SDL.

	Copyright (C) 2011 Pierre Veber
	
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software Foundation,
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
------------------------------------------------------------------------------
*/

#define IMAGE_JPEG	(int)0
#define IMAGE_PNG	(int)1

/*
 ------------------------------------------------------------------------------
	Fast heap management.
		Provides post/get message and thread message queue to SDL_Thread.
 ------------------------------------------------------------------------------
*/

struct FastHeap_t;
typedef FastHeap_t* HFastHeap;

HFastHeap
wp_fast_heap_new(
	size_t nPageSize
	);

void*
wp_fast_heap_alloc(
	FastHeap_t* pHeap,
	size_t s
	);

void*
wp_fast_heap_dup(
	FastHeap_t* pHeap,
	const void* pSource,
	size_t nSize
	);

void
wp_fast_heap_free(
	FastHeap_t* pHeap
	);

/*
 ------------------------------------------------------------------------------
	Thread management.
		Provides post/get message and thread message queue to SDL_Thread.
 ------------------------------------------------------------------------------
*/

struct ThreadHandle_t;
typedef ThreadHandle_t* HThread;

typedef int (*ThreadFunc)(HThread, void *);

struct ThreadMessage_t
{
	int				iMsgCode;
	unsigned long	ulParam1;
	unsigned long	ulParam2;
};

HThread
CreateThread(
		ThreadFunc tf,
		void* pData
		);

void
DeleteThread(
		HThread pHandle
		);

int
PostThreadMessage(
		HThread pHandle,
		int iCode,
		unsigned long	ulParam1,
		unsigned long	ulParam2
		);

int
GetThreadMessage(
		HThread pHandle,
		ThreadMessage_t* pMsg
		);

/*
 ------------------------------------------------------------------------------
	Audio device management.
		Each platform / audio engine should implement the functions below
 ------------------------------------------------------------------------------
*/

struct AudioDevice_t;
typedef AudioDevice_t* HAudioDevice;

HAudioDevice
waveOpen();

int	
waveWriteIn(
	HAudioDevice hAudio,
	const void* pBuffer,
	unsigned int frames
	);

void
waveReset(
	HAudioDevice hAudio
	);

void
wavePause(
	HAudioDevice hAudio
	);

void
waveRestart(
	HAudioDevice hAudio
	);

void
waveSetVolume(
	HAudioDevice hAudio,
	WORD wVolume
	);

void
waveClose(
	HAudioDevice hAudio
	);

/*
 ------------------------------------------------------------------------------
	Audio library management.
		Audio library manages audio files on disk and playlists.
 ------------------------------------------------------------------------------
*/

struct TrackInfo_t
{
	Uint16* pszArtist;
	Uint16* pszAlbum;
	Uint16* pszTrack;
	Uint16* pszYear;
	Uint16* pszTrackNum;
	Uint16* pszMsLength;
};

struct AudioFile_t
{
	char* pszFullPath;
	TrackInfo_t info;
	int iDecoder;
	struct AudioFile_t* pNext;
};

struct AudioList_t
{
	AudioFile_t* pHead;
	AudioFile_t* pTail;
	AudioFile_t* pCurrent;
	int nFiles;
	
	struct AudioFile_t* pNext;
};

struct AudioLib_t;

typedef AudioFile_t*	HAudioFile;
typedef AudioList_t*	HAudioList;
typedef AudioLib_t*		HAudioLib;

#define LIB_STATUS_FILE_ACCESS	0x00000001
#define LIB_STATUS_ID3_ACCESS	0x00000002

typedef int (*HandleLibStatus)(AudioLib_t*, int);

AudioLib_t*
libCreate(
	const char* pszPath
	);

int
libFill(
	HAudioLib hLib,
	HandleLibStatus fp
	);

void
libFree(
	HAudioLib hLib
	);

HAudioList
playlistCreate(
	);

HAudioList
playlistFromLib(
	HAudioLib hLib
	);

void
playlistAdd(
	HAudioList hList,
	HAudioFile hFile
	);

HAudioFile
playlistLookupFile(
	AudioList_t* pList,
	const char* pszFilePath
	);

void
playlistFree(
	HAudioList hList
	);

/*
 ------------------------------------------------------------------------------
	Decoder.
		Base virtual class to implement an audio decoder (e.g. as plugin)
 ------------------------------------------------------------------------------
*/

#define DECODE_STATUS_NONE		0
#define DECODE_STATUS_DECODING	1
#define DECODE_STATUS_FINISHED	2
#define DECODE_STATUS_PAUSED	3
#define DECODE_STATUS_STOPPED	4

class CWPDecoder 
{
public:

	CWPDecoder() { this->hAudio = NULL; };
	virtual ~CWPDecoder() {};

	/* decoder information functions */
	virtual const char* name() = 0;
	virtual const char* extensions() = 0;
	virtual void setAudioDevice(HAudioDevice hAudio) { this->hAudio = hAudio; }

	/* decoding functions */
	virtual int prepare(char* lpszFileToDecode) = 0;
	virtual int decode() = 0;
	virtual int pause() = 0;
	virtual int stop() = 0;
	virtual int seek(int) = 0;
	
	/* file information (tag) function */
	virtual int getInfo(AudioFile_t*, MallocProc, void*) = 0;
	virtual SDL_Surface* getPicture(AudioFile_t*) = 0;

protected:
	HAudioDevice hAudio;
};

/* 
list all decoders here
	declare global in specific decoder source file
	*/
extern CWPDecoder* _g_pMadDecoder;

/* 
global decoders list
	declared in audiolib.cpp
	*/
extern CWPDecoder** _g_ppDecoders;

/* 
global decoders list
	implemented in audiolib.cpp
	*/
#define ENODEC	(int)-1
int decoderIndex(char* pszFileName);

/*
 ------------------------------------------------------------------------------
	Player management.
		Player manages the decoders and decode thread
 ------------------------------------------------------------------------------
*/

struct Player_t;
typedef Player_t* HPlayer;

HPlayer
playerCreate (
	HAudioDevice hAudio
	);

int
playerQueue(
	HPlayer hPlayer,
	AudioFile_t* pFile
	);

int
playerResume(
	HPlayer hPlayer
	);

int
playerPause(
	HPlayer hPlayer
	);

int
playerSeek(
	HPlayer hPlayer,
	int amt
	);

int
playerStop(
	HPlayer hPlayer
	);

int
playerGetInfo(
	HPlayer hPlayer
	);

void
playerDelete(
	HPlayer hPlayer
	);
